<!DOCTYPE html>
<html lang="en">
<head>
    <title>Openfire: TLS Guide</title>
    <link type="text/css" rel="stylesheet" href="style.css">
</head>
<body>

<article>

    <header>
        <img src="images/header_logo.gif" alt="Openfire Logo" />
        <h1>TLS Guide</h1>
    </header>

    <nav>
        <a href="index.html">&laquo; Back to documentation index</a>
    </nav>

    <section id="intro">

        <h2>Introduction</h2>

        <p>
            This document outlines how to <b>manually</b> customize the SSL support in
            Openfire. As of Openfire 3.2 certificate management can be performed from the
            Admin Console. However, if needed you can still manually manage certificates
            using Java Development Kit (JDK) tools.
        </p>
        <p>
            <span style="color: red; "><b>Important note:</b></span>
            Once the setup process is completed Openfire will create self-signed certificates
            for the assigned Openfire's domain. Most users should either get the created
            certificates signed by a Certificate Authority or replace the created certificates
            with your own certificates.
        </p>
        <p>
            Openfire's SSL support is built using the standard Java security
            SSL implementation (javax.net.ssl.SSLServerSocket). In this document, we will
            describe how use the standard Java Development Kit (JDK) tools to accomplish these tasks.
        </p>

        <p>Topics that are covered in this document:</p>

        <nav>
            <ul>
                <li><a href="#background">Background</a></li>
                <li><a href="#tools">Oracle Java Development Kit security tools</a></li>
                <li><a href="#revocation">Certificate Revocation Configuration</a></li>
                <li><a href="#misc">Other options</a></li>
            </ul>
        </nav>

    </section>

    <section id="background">

        <h2>Background</h2>

        <p>
            A server SSL connection uses two sets of certificates to secure the
            connection. The first set is called a "keystore". The keystore contains
            the keys and certificates for the server. These security credentials
            are used to prove to clients that the server is legitimately operating
            on behalf of a particular domain. If your server will only need to act
            as one domain, you only need one key entry and certificate in the keystore.
            Keys are stored in the keystore under aliases. Each alias corresponds
            to a domain name (e.g. "example.com").
        </p>
        <p>
            The second set of certificates is called the "truststore" and is used
            to verify that a client is legitimately operating on behalf of a
            particular user. In the vast majority of cases, the truststore is
            empty and the server will not attempt to validate client connections
            using SSL. Instead, the XMPP authentication process verifies users
            in-band. However, you may wish to require SSL authentication for
            certain clients when security is especially important and the number
            of clients connection to the server is relatively small.
        </p>
        <p>
            Certificates attempt to guarantee that a particular party is who they
            claim to be. Certificates are trusted based on who signed the certificate.
            If you only require light security, are deploying for internal use on
            trusted networks, etc. you can use "self-signed" certificates.
            Self-signed certificates encrypts the communication channel between
            client and server. However, the client must verify the legitimacy of the
            self-signed certificate through some other channel. The most common client
            reaction to a self-signed certificate is to ask the user whether
            to trust the certificate, or to silently trust the certificate is
            legitimate. Unfortunately, blindly accepting self-signed certificates
            opens up the system to 'man-in-the-middle' attacks.
        </p>
        <p>
            The advantage of a self-signed certificate is you can create them for
            free which is great when cost is a major concern, or for testing and evaluation.
            In addition, you can safely use a self-signed certificate if you can verify
            that the certificate you're using is legitimate. So if a system administrator
            creates a self-signed certificate, then personally installs it on a client's
            truststore (so that the certificate is trusted) you can be assured that
            the SSL connection will only work between the client and the correct server.
        </p>
        <p>
            For higher security deployments, you should get your certificate signed
            by a certificate authority (CA). Clients truststores will usually contain
            the certificates of the major CA's and can verify that a CA has signed a
            certificate. This chain of trust allows clients to trust certificate from
            servers they've never interacted with before. Certificate signing is similar
            to a public notary (with equivalent amounts of verification of identity,
            record keeping, and costs).
        </p>
    </section>

    <section id="tools">

        <h2>Oracle Java Development Kit security tools</h2>
        <p>
            The Oracle JDK ships with all the security tools you need to configure SSL with Openfire. The most important
            is the <code>keytool</code> located in the <code>JAVA_HOME/bin directory</code> of the JDK. Java Virtual
            Machines persist keystores and truststores on the filesystem as encrypted files. The <code>keytool</code> is
            used to create, read, update, and delete entries in these files. Openfire ships with a self-signed "dummy"
            certificate designed for initial evaluation testing. You will need to adjust the default configuration for
            most deployments.
        </p>
        <p>
            In order to configure SSL on your server you need complete the following tasks:
        </p>
        <ol>
            <li>Decide on your Openfire server's domain.</li>
            <li>
                Create a self-signed SSL server certificate for your server domain. Note: you may already have one if
                your Openfire server domain matches an existing web domain with SSL. If so, you can skip to step 4.
            </li>
            <li>[Optional] Have a certificate authority (CA) certify the SSL server certificate.
                <ol style="list-style-type: lower-alpha;">
                    <li>Generate a certificate signing request (CSR).</li>
                    <li>Submit your CSR to a CA for signing.</li>
                </ol>
            </li>
            <li>
                Import the server certificate into the keystore. Note: if you are going to use a self-signed certificate
                generated in step 2, the certificate is already imported, and you can skip this step.
            </li>
            <li>Remove default certificates from the keystore.</li>
            <li>Import client certificates into the truststore.</li>
            <li>Adjust the Openfire configuration with proper keystore and truststore settings.</li>
        </ol>

        <section>

            <h3>1. Decide on a Server Domain</h3>

            <p>
                The Openfire server domain should match the host name of the server;
                for example, "example.com". Your user accounts will have addresses with
                the format "user@example.com" like email addresses. We'll assume
                the domain is "example.com" for the rest of the examples.
            </p>

        </section>

        <section>

            <h3>2. Create a self-signed server certificate</h3>

            <p>
                In order to create a self-signed server certificate go to the command
                line and change directories to the <code>resources/security</code>
                directory of your Openfire installation. You should see the default
                <code>keystore</code> and <code>truststore</code> files. First, you should
                change the default keystore
                password:
            </p>
            <pre>keytool -storepasswd -keystore keystore</pre>
            <p>
                keytool will ask for the old password (by default it is <code>changeit</code>)
                then the new password. Now we'll create a certificate using the keytool:
            </p>
            <pre>keytool -genkey -keystore keystore -alias example.com</pre>
            <p>
                where you should substitute your server's name for <code>example.com</code>.
                The keytool will ask for the store password, then several pieces of
                information required for the certificate. Enter all the information but remember
                to <b>complete with your server's name when asked for your first and last name</b>.
                After you have entered all the required information, keytool will ask you to
                verify the information and set a key password.
                <b>You must use the same key password as the store password.</b> By default,
                you get this by simply hitting 'enter' when prompted for a key password.
            </p>
            <p>
                If you later change the keystore password remember to change the entries'
                password as well using the keytool:
            </p>
            <pre>keytool -keypasswd -alias example.com -keystore keystore</pre>
            <p>
                Keytool will create certificates using the DSA algorithm by default. Some clients
                expect the server to have RSA certificates or they will fail to use TLS. Therefore,
                it is a good idea to also create RSA certificates in your keystore. To create
                certificates with the RSA algorithm you need to specify the algorithm to use like this:
            </p>
            <pre>keytool -genkey -keystore keystore -alias example.com -keyalg RSA</pre>

        </section>

        <section>

            <h3>3. Obtain a CA signed certificate</h3>
            <p>
                If you decide to get a CA signed certificate, you must first export the
                certificate in the standard CSR format. You can do this with the keytool:
            </p>
            <pre>keytool -certreq -keystore keystore -alias example.com -file certificate_file</pre>
            <p>
                Where you should substitute your server's name for <code>example.com</code>
                and the name of the certificate file you wish to produce for <code>certificate_file</code>.
                Submit the generated CSR to the CA and follow their instructions to get it signed.
            </p>

        </section>

        <section>

            <h3>4. Import server certificates</h3>
            <p>
                If you had a CA sign your server certificate, or if you have an
                existing SSL certificate, you must import it using the keytool.
            </p>
            <pre>keytool -import -keystore keystore -alias example.com -file signed_certificate_file</pre>
            <p>
                It is important that the alias not already have an associated key or
                you'll receive an error.
            </p>

        </section>

        <section>

            <h3>5. Remove default certificates</h3>
            <p>
                After importing your certificate you must remove the default certificates
                using the keytool.
            </p>
            <pre>keytool -delete -keystore keystore -alias rsa</pre>
            <pre>keytool -delete -keystore keystore -alias dsa</pre>

        </section>

        <section>

            <h3>6. Import client certificates</h3>
            <p>
                If you require clients to verify themselves using certificates, obtain
                their certificates and import them into the truststore file rather than
                the keystore. First, you should change the default truststore
                password:
            </p>
            <pre>keytool -storepasswd -keystore truststore</pre>
            <p>
                keytool will ask for the old password (by default it is <code>changeit</code>)
                then the new password. Now import each certificate using the keytool:
            </p>
            <pre>keytool -import -keystore truststore -alias user_name -file certificate_file</pre>

        </section>

        <section>

            <h3>7. Configure Openfire</h3>
            <p>
                Open the Openfire Admin Console in your favorite
                browser and add or change the following system properties:
            </p>
            <dl>
                <dt>xmpp.socket.ssl.active</dt>
                <dd>set to 'true' to active SSL</dd>

                <dt>xmpp.socket.ssl.port</dt>
                <dd>the port to use for SSL (default is 5223 for XMPP)</dd>

                <dt>xmpp.socket.ssl.storeType</dt>
                <dd>the store type used ("JKS" is the Sun Java Keystore format used by the JDK keytool). If this property is not defined, Openfire will assume a value of "jks".</dd>

                <dt>xmpp.socket.ssl.keystore</dt>
                <dd>the location of the keystore file relative to your Openfire installation root directory. You can leave this property blank to use the default keystore.</dd>

                <dt>xmpp.socket.ssl.keypass</dt>
                <dd>the keystore/key password you changed in step 2.</dd>

                <dt>xmpp.socket.ssl.truststore</dt>
                <dd>leave blank to not use a  truststore, otherwise the location of the truststore file relative to your Openfire installation root directory.</dd>

                <dt>xmpp.socket.ssl.trustpass</dt>
                <dd>the truststore/key password you changed in step 6.</dd>
            </dl>
            <p>
                You will need to restart the server after you have modified any of the above system properties.
            </p>
        </section>

    </section>


    <section id="revocation">
        <h2>Certificate Revocation</h2>

        <p>This section covers the configuration of certificate revocation checking in Openfire, including OCSP
            (Online Certificate Status Protocol) and CRL (Certificate Revocation List) mechanisms. This applies to
            both roles that Openfire can assume in TLS connections:</p>

        <ol>
            <li>As a server when:
                <ul>
                    <li>Accepting client connections (C2S)</li>
                    <li>Accepting incoming server-to-server (S2S) connections</li>
                </ul>
            </li>
            <li>As a client when:
                <ul>
                    <li>Initiating outbound server-to-server (S2S) connections</li>
                </ul>
            </li>
        </ol>

        <h3>Overview of Revocation Checking Methods</h3>

        <p>Openfire supports three methods for checking certificate revocation status:</p>

        <ol>
            <li><strong>OCSP Stapling</strong>: The server attaches ("staples") the OCSP response to its certificate
                during the TLS handshake.
                <ul>
                    <li>Most efficient method</li>
                    <li>Reduces load on OCSP responders</li>
                    <li>Supported in both client and server roles</li>
                </ul>
            </li>

            <li><strong>Client-driven OCSP</strong>: Direct OCSP responder queries to verify certificate status.
                <ul>
                    <li>Real-time verification</li>
                    <li>Higher network overhead</li>
                    <li>Increased latency during TLS handshake</li>
                </ul>
            </li>

            <li><strong>Certificate Revocation Lists (CRL)</strong>: Downloadable lists of revoked certificates.
                <ul>
                    <li>Periodic updates</li>
                    <li>Can be cached locally</li>
                    <li>Larger bandwidth requirements</li>
                    <li>Can be used as a fallback method</li>
                </ul>
            </li>
        </ol>

        <h3>Configuring Revocation Checking</h3>

        <p>To enable certificate revocation checking:</p>

        <ol>
            <li>Go to the Openfire admin console.</li>
            <li>Navigate to "Server / Server Settings / Server to Server" or "Server / Server Settings / Client Connections".</li>
            <li>In the "Certificate chain checking" section, locate the option labelled "Verify that certificates have not been revoked (by checking Certificate Revocation Lists and OCSP)".</li>
            <li>Enable the option to verify certificates against Certificate Revocation Lists (CRL) and through Online Certificate Status Protocol (OCSP).</li>
        </ol>

        <p>When this option is enabled, Openfire will check the revocation status of certificates used in server-to-server
            (S2S) and client-to-server (C2S) connections to ensure they have not been revoked.</p>

        <h4>Fallback behavior when Openfire is the Client (S2S Connections)</h4>

        <p>When revocation checking is enabled, Openfire employs a multistep process to verify certificate validity
            using both OCSP and CRLs. When Openfire acts as a client during the TLS handshake and receives certificates
            from a server, it performs the following revocation checking process:</p>
        <ol>
            <li>Check OCSP stapled response (if available)</li>
            <li>Attempt client-driven OCSP query if no stapled response is present</li>
            <li>Check CRL (if OCSP is unavailable, and CRL is available)</li>
            <li>Allow the connection to succeed if the revocation status cannot be determined</li>
        </ol>

        <p>The system property <code>xmpp.socket.ssl.certificate.revocation.soft-fail</code> controls the behavior when
            revocation status cannot be determined. The default value of this property is <code>false</code> which fails
            the connection if the revocation status of a certificate cannot be determined. If you want to relax
            revocation checking, you can set this property to <code>true</code>. When set to <code>true</code>, the
            connection will be allowed if a certificate's revocation status cannot be established.</p>

        <p>By default, revocation checking considers the entire certificate chain. If you want to limit revocation
            checking to only the leaf certificate in a chain you can set the system
            property <code>xmpp.socket.ssl.certificate.revocation.only-end-entity</code> to <code>true</code>.</p>

        <h4>OCSP Stapling</h4>

        <p>Openfire, when operating as a TLS server and presenting its own certificate, will attempt to staple OCSP
            responses when both of these conditions are met:</p>

        <ul>
            <li>The certificate includes an OCSP responder URL in its Authority Info Access (AIA) extension.</li>
            <li>The specified OCSP responder returns a valid (non-error) response.</li>
        </ul>

        <p>If an OCSP response cannot be obtained, Openfire will present the certificate without an OCSP staple.
            OCSP stapling improves performance by eliminating the need for clients to make separate requests to
            verify certificate revocation status.</p>

        <p>OCSP stapling is enabled by default. If you need to disable it for any reason, you can set the Java
            system property <code>jdk.tls.server.enableStatusRequestExtension</code> to <code>false</code>.</p>

        <p>
            The following configuration options allow you to customise OCSP stapling behavior:
        </p>
        <table class="general">
            <thead>
            <tr>
                <th>Property</th>
                <th>Description</th>
                <th>Openfire Default Value</th>
            </tr>
            </thead>
            <tbody>
            <tr>
                <td><code>jdk.tls.server.enableStatusRequestExtension</code></td>
                <td>Enables the server-side support for OCSP stapling.</td>
                <td>True</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.responseTimeout</code></td>
                <td>
                    <p>Controls the maximum amount of time the server will use to obtain OCSP responses, whether from the cache or by contacting an OCSP responder.</p>
                    <p>The responses that are already received will be sent in a <code>CertificateStatus</code> message, if applicable based on the type of stapling being done.</p>
                </td>
                <td>5000 (integer value in milliseconds)</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.cacheSize</code></td>
                <td>
                    <p>Controls the maximum cache size in entries.</p>
                    <p>If the cache is full and a new response needs to be cached, then the least recently used cache entry will be replaced with the new one. A value of zero or less for this property means that the cache will have no upper bound on the number of responses it can contain.</p>
                </td>
                <td>256 objects</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.cacheLifetime</code></td>
                <td>
                    <p>Controls the maximum life of a cached response.</p>
                    <p>It is possible for responses to have shorter lifetimes than the value set with this property if the response has a <strong>nextUpdate</strong> field that expires sooner than the cache lifetime. A value of zero or less for this property disables the cache lifetime. If an object has no <strong>nextUpdate</strong> value and cache lifetimes are disabled, then the response will not be cached.</p>
                </td>
                <td>3600 seconds (1 hour)</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.responderURI</code></td>
                <td>
                    <p>Enables the administrator to set a default URI in the event that certificates used for TLS do not have the Authority Info Access (AIA) extension.</p>
                    <p>It will not override the Authority Info Access extension value unless the <code>jdk.tls.stapling.responderOverride</code> property is set.</p>
                </td>
                <td>Not set</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.responderOverride</code></td>
                <td>
                    <p>Enables a URI provided through the <code>jdk.tls.stapling.responderURI</code> property to override any AIA extension value.</p>
                </td>
                <td>False</td>
            </tr>
            <tr>
                <td><code>jdk.tls.stapling.ignoreExtensions</code></td>
                <td>
                    <p>Disables the forwarding of OCSP extensions specified in the <code>status_request</code> or <code>status_request_v2</code> TLS extensions.</p>
                </td>
                <td>False</td>
            </tr>
            </tbody>
        </table>

    </section>

    <section id="misc">

    <h2>Other options</h2>
    <p>
        You can also use OpenSSL to create new private keys and generate certificate requests for your CA to issue new certificates.
        Also, check out the new <a href="https://www.igniterealtime.org/projects/openfire/plugin-archive.jsp?plugin=certificatemanager">Certificate Manager</a> plugin,
        which allows to set up a hotdeploy directory for new certificates deployment, which in turn combined with Let's Encrypt certbot
        allows dynamic certificates renewal without administrator intervention.
    </p>

    </section>

    <footer>
        <p>
            An active support community for Openfire is available at
            <a href="https://discourse.igniterealtime.org">https://discourse.igniterealtime.org</a>.
        </p>
    </footer>

</article>
</body>
</html>
